/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.composite.editpart;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.gef.DragTracker;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.ElementImport;
import org.eclipse.uml2.uml.Port;

import com.cea.papyrus.core.editor.ModelManager;
import com.cea.papyrus.core.editpart.DiagramEditPart;
import com.cea.papyrus.core.editpart.GraphNodeWithSemanticEditPart;
import com.cea.papyrus.core.editpart.LinkNameDisplayEditPart;
import com.cea.papyrus.core.figures.ElementFigure;
import com.cea.papyrus.core.figures.IconFigure;
import com.cea.papyrus.core.figures.NodeFigure;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagram.composite.helper.NodePortHelper;
import com.cea.papyrus.diagram.composite.listener.PortListener;
import com.cea.papyrus.diagraminterchange2.di2.GraphNode;
import com.cea.papyrus.diagraminterchange2.di2.Uml1SemanticModelBridge;

/**
 * Controller for a {@link Port}.
 */
public class PortEditPart extends GraphNodeWithSemanticEditPart {

	/** associated name editpart */
	protected  LinkNameDisplayEditPart nameEditpart;

	/**
	 * Creates a new PortEditPart
	 * @param graphNode the graph node representing the port
	 * @param modelManager the model manager associated to the editor
	 */
	public PortEditPart(GraphNode graphNode,ModelManager modelManager) {
		super(graphNode,modelManager);
		_adapter= new PortListener(this);
	}

    /**
     * Install diagram specific editPolicy
     */
    @Override
    protected void createEditPolicies(){
        super.createEditPolicies();
        // overload the GRAPHICAL_NODE_ROLE editPolicy to use the diagram specific one
        installEditPolicy(EditPolicy.GRAPHICAL_NODE_ROLE, new GraphNodeEditPolicy() );
    }

    /* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#getNodeFigure()
	 */
	@Override
	protected ElementFigure getNodeFigure(){
		return (ElementFigure)createFigure() ;
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#createFigure()
	 */
	@Override
	protected IFigure createFigure() {
		// Try to get figure from ContainerWithSemanticEditPart
		IFigure fig = super.createFigure();
		
		if (fig != null) {
			return fig;
		}
		// else
		return new ElementFigure();	
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
	 */
	@Override
	protected List getModelChildren() { //look for all graphnodes, 
		ArrayList contained= new ArrayList();//that is associated to label

	// 	contained.add(getGraphNode().getContained().get(0));
		return contained;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractEditPart#addChild(org.eclipse.gef.EditPart, int)
	 */
	@Override
	protected void addChild(EditPart child, int index) {
		if (child.equals(nameEditpart)){
			((DiagramEditPart)getParent()).addExplicitEditpart(nameEditpart, index);
		}
		else {
			super.addChild(child, index);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#getDragTracker(org.eclipse.gef.Request)
	 */
	@Override
	public DragTracker getDragTracker(Request request) {
		return new PortDragTracker(this);
	}
	
	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#activate()
	 */
	@Override
	public void activate() {
		if (isActive()) {
			Debug.debug(this, "should not activate an already active edit part", channel);
			return;
		}
		// start listening for changes in the model
		((Notifier)getGraphNode()).eAdapters().add(_adapter);
		super.activate();
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#deactivate()
	 */
	@Override
	public void deactivate() {
		if (!isActive()) {
			Debug.debug(this, "should not deactivate an already deactived edit part", channel);
			return;
		}
		// stop listening for changes in the model
		((Notifier)getGraphNode()).eAdapters().remove(_adapter);
		super.deactivate();
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#refreshVisuals()
	 */
	@Override
	protected void refreshVisuals() {
		/** Stereotype presentation */
		Dimension size = getGraphNode().getSize();
		Point p = getGraphNode().getPosition();
		Rectangle r = new Rectangle(p ,size);

		IFigure fig = getFigure();
		// this is a shape
		if (!(fig instanceof ElementFigure)) {
			IconFigure icf= (IconFigure)getFigure();
			icf.setName("");
		} else {
			// Retrieve current class and figure
			org.eclipse.uml2.uml.Port currentPort = getUmlElement();
//			com.cea.utils.Element currentElement = new com.cea.utils.Element(getUmlElement());

			// refresh presentation
//			ElementFigure pt = (ElementFigure) fig; //get elementFigure
			((NodeFigure) fig).refreshColors(getGraphNode());
			((NodeFigure) fig).refreshPresentation(getPresentation(), currentPort, getGraphNode());

//			boolean hasIcon  = currentElement.hasIcon();
//			boolean hasShape = currentElement.hasShape();
		}
		((GraphicalEditPart) getParent()).setLayoutConstraint(
				this,
				fig,
				r);
	}

	/* (non-Javadoc)
	 * @see com.cea.papyrus.common.editpart.GraphNodeWithSemanticEditPart#getUmlElement()
	 */
	@Override
	public org.eclipse.uml2.uml.Port getUmlElement() {
		Element e=((Uml1SemanticModelBridge)getGraphNode().getSemanticModel()).getElement();
		if(e instanceof ElementImport){//may be an Element import
			return (Port)((ElementImport)e).getImportedElement();
		}
		return ((Port)e);
	}
	
	/**
	 * Calculates the good position of a port by taking account his parent.
	 * @param point the position of the current port in absolute coordinate
	 * @return the new position of the port.
	 */
	public Point inRunnerOfClass(Point point){
		Dimension portDimension=getGraphNode().getSize();
		//apply good position , the defaut is the same point
		//FIXME should be a nodehelper called from the plugin
		NodePortHelper np= new NodePortHelper();
		return np.inRunner((GraphNode)getGraphNode().getSemanticParent(), point, portDimension);
	}
	
    /**
     * Return false.
     * This method is used in {@link com.cea.papyrus.common.editpart.LayoutEditPolicy} in order to
     * know how to compute the coordinate of a added part.
     * @TODO move this method to more appropriate place. 
     * @return
     */
    @Override
    public boolean needRelativeTranslationForAddCommand()
    {
        return false;
    }
	
}
